/*
 * Copyright (c) 2010 Toni Spets <toni.spets@iki.fi>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "common.h"
#include "launcher.h"
#include "thipx32.h"

void hook_IPX_Initialise(CONTEXT *ctx)
{
    ctx->Eax = (uint32_t)_IPX_Initialise();
}

void hook_IPX_Start_Listening95(CONTEXT *ctx)
{
    ctx->Eax = (uint32_t)_IPX_Start_Listening95();
}

void hook_IPX_Shut_Down95(CONTEXT *ctx)
{
    ctx->Eax = (uint32_t)_IPX_Shut_Down95();
}

void hook_IPX_Send_Packet95(CONTEXT *ctx)
{
    char addr[8];
    char buf[1024];

    void *p1 = (void *)pop(ctx);
    void *p2 = (void *)pop(ctx);
    int p3 = (int)pop(ctx);
    pop(ctx);
    pop(ctx);

    memread(p1, addr, 8);
    memread(p2, buf, p3);

    #ifdef CNCNET_CLIENT
        ThreadingVector<Packet>* incomingPacket = LauncherHooks::incomingPacketInstance();
        Packet packet;
        packet.setType(OutgoingPacket);
        packet.setAddr(addr);
        packet.setMessage(buf, p3);
        incomingPacket->addData(packet);
    #endif

    /* I do not know what the last 2 parameters are and CnCNet works without them */
    ctx->Eax = _IPX_Send_Packet95(addr, buf, p3, NULL, NULL);
}

void hook_IPX_Broadcast_Packet95(CONTEXT *ctx)
{
    char buf[1024];
    char *p1 = (char *)pop(ctx);
    int p2 = (int)pop(ctx);

    memread(p1, buf, p2);

    #ifdef CNCNET_CLIENT
        ThreadingVector<Packet>* incomingPacket = LauncherHooks::incomingPacketInstance();
        Packet packet;
        packet.setType(OutgoingBroadcast);
        packet.setMessage(buf, p2);
        incomingPacket->addData(packet);
    #endif

    ctx->Eax = _IPX_Broadcast_Packet95(buf, p2);
}

void hook_IPX_Get_Outstanding_Buffer95(CONTEXT *ctx)
{
    char buf[1024];
    char *p1 = (char *)pop(ctx);
    int ret;

    ret = _IPX_Get_Outstanding_Buffer95(buf);
    if(ret)
    {
        memwrite(p1, buf, 1024);
        #ifdef CNCNET_CLIENT
            ThreadingVector<Packet>* incomingPacket = LauncherHooks::incomingPacketInstance();
            Packet packet;
            packet.setType(IncomingPacket);
            packet.setMessage(buf, 1024);
            incomingPacket->addData(packet);
        #endif

        ctx->Eax = 1;
    }
    else
    {
        ctx->Eax = 0;
    }
}

void hook_IPX_Open_Socket95(CONTEXT *ctx)
{
    int p1 = (int)pop(ctx);

    ctx->Eax = _IPX_Open_Socket95(p1);
}

void hook_IPX_Close_Socket95(CONTEXT *ctx)
{
    int p1 = (int)pop(ctx);
 
    ctx->Eax = _IPX_Close_Socket95(p1);
}

void hook_IPX_Get_Connection_Number95(CONTEXT *ctx)
{
    ctx->Eax = _IPX_Get_Connection_Number95();
}

void hook_IPX_Get_Local_Target95(CONTEXT *ctx)
{
    uint32_t p1 = pop(ctx);
    uint32_t p2 = pop(ctx);
    uint32_t p3 = pop(ctx);
    uint32_t p4 = pop(ctx);

    ctx->Eax = _IPX_Get_Local_Target95((uint32_t *)p1, (uint32_t *)p2, (uint32_t *)p3, (uint32_t *)p4);
}
